
/* interpreter.h: заголовочный файл, содержащий функции интерпретатора */

#ifndef INTERPRETER_H
#define INTERPRETER_H

//==================================================================================================================
#include "preproc.h"		// подключение библиотеки с базовыми константами, макросами, типами данных и структурами
//==================================================================================================================

//===================================================================================================================================
uint	get_args_count	(string);				// подсчет количества аргументов
uint	get_next_space	(string, uint);			// функция нахождения ближайшего пробела
string	get_str			(string, uint, uint);	// функция выделения подстроки
string*	get_args		(string);				// выделение аргументов
string	get_cmd			(string);				// функция, выделяющая первое слово
void*	a_malloc		(uint);					// функция выделения памяти
int		a_free			(void*);				// функция удаления элемента
void*	unbind_ptr		(void*);				// функция отвязки от корзины
void	show_trash		(string);				// функция вывода корзины
void	clear_trash		(void);					// функция очищения "корзины"
void	prints			(string);				// функция вывода строки
uint	get_hash		(string);				// функция получения хеша
uint	str_len			(string);				// функция определения длины строки
string	get_value		(string*, int, string);	// функция получения флага из строки
string	get_path		(string);				// функция изменения и получения рабочей директории
// string cgets(int max_size);					// функция интелектуального ввода
//===================================================================================================================================
uint get_args_count(string str)     					// подсчет количества аргументов
{
	register uint	c = 0,          					// переменная подсчета количества пробелов
					i;              					// счетчик

	for(i = 0; str[i] != EOS and str[i] != '\n'; ++i)	// цикл подсчета пробелов
		if(str[i] == ' ' or str[i] == '\t')				// проверка пробела (текущий символ - пробел)
			++c;                    					// инкремент переменной подсчета аргументов

	return c;	                     					// возвращаем количество пробелов
}
//=======================================================================================================================================================================================================
uint get_next_space(string str, uint offset)					// функция нахождения ближайшего пробела
{
	register uint i = 0;                    					// сдвиг в строке

	while(str[offset + i] != EOS and str[offset + i] != '\n')	// цикл обхода строки
	{
		if(str[offset + i] == ' ' or str[offset + i] == '\t')	// проверка текущего символа (текущий символ - пробельный)
			return i;                       					// возвращаем положение текущего символа
		else                                					// текущий символ не пробельный
			++i;                            					// инкремент сдвига
	}

	return i;													// возвращаем сдвиг
}
//=======================================================================================================================================================================================================
string get_str(string str, uint offset, uint len)						// функция выделения подстроки
{
	string			tmp = (string) a_malloc((len + 1) * sizeof(char));	// выделение памяти под массив строк
	register uint	i;													// счетчик цикла

	for(i = 0; i < len; ++i)											// цикл копирования, [0;len)
		tmp[i] = str[offset + i];										// копирование offset + i в i

	tmp[len] = EOS;														// добавление символа окончания строки

	return tmp;															// возвращаем подстроку
}
//===================================================================================================================================
string* get_args(string str)                                    			// выделение аргументов
{
	register uint	i;                                          			// счетчик
	uint    		c           = get_args_count(str),                  	// переменная количества аргументов комманды
					offset      = get_next_space(str, 0) + 1,           	// переменная отступа
					full_adr    = offset;                               	// переменная адреса начала следующего аргумента
	string* 		buff        = (string* )a_malloc(c * sizeof(string));	// массив аргументов

	for(i = 0; i < c; ++i)	                                     			// цикл выделения памяти под массив строк
		buff[i] = (string) a_malloc(sizeof(char) * MAX_LEN);     			// выделение памяти под строку

	for(i = 0; i < c; ++i)  	                                   			// цикл выделения аргументов
	{
		offset      =   get_next_space(str, full_adr);          			// нахождение положения следующего пробела относительно предыдущего
		buff[i]     =   get_str(str, full_adr, offset);         			// выделение подстроки
		++ offset;                                      					// увеличение значения длины аргумента на 1
		full_adr    +=  offset;                                 			// увеличение абсолютного отступа
	}

	return buff;                                                			// возвращаем массив аргументов
}
//===================================================================================================================================
string get_cmd(string str)                          // функция, выделяющая первое слово
{
	/* выделение памяти под слово */
	string buff = (string) a_malloc((get_next_space(str, 0) + 1) * sizeof(char));

	buff = get_str(str, 0, get_next_space(str, 0)); // запись подстроки

	buff[get_next_space(str, 0)] = EOS;             // "закрытие" строки

	return buff;                                    // возвращаем строку
}
//===================================================================================================================================
void* a_malloc(uint bytes)				// функция выделения памяти
{
	if(trash_p < MAX_ALLOCATED_MEM)		// проверка выделенной памяти под строки (строк меньше максимального количества)
	{
		void *tmp      = malloc(bytes);	// выделение памяти

		trash[trash_p] = tmp;			// запоминаем указатель на выделенную область памяти
		++trash_p;						// смещение указателя текущей ячейки на следующую

		return tmp;						// возвращаем адрес выделенной области памяти
	}
	else								// строк больше максимального количества
		return NULL;					// возвращаем нулевй указатель
}
//===================================================================================================================================
int a_free(void* ptr)								// функция удаления элемента из корзины
{
	if(ptr)											// проверка существования указателя (указатель существует)
	{
		register usint i;							// счетчик

		for(i = 0; i < trash_p; ++i)				// цикл обхода существующих элементов корзины
		{
			if(ptr == trash[i])						// проверка текущего указателя (текущий указатель - искомый)
			{
				free(trash[i]);						// освобождение памяти по найденному адресу

				--trash_p;							// декремент значения указателя последнего элемента корзины

				trash[i]		= trash[trash_p];	// перезапись очищенной ячейки последней занятой ячейкой корзины
				trash[trash_p]	= NULL;				// обнуление последней занятой ячейки

				return SUCCESS;						// сообщение об успешном выполнении операции
			}
		}
	}

	return ERROR;									// сообщение об ошибке
}
//===================================================================================================================================
void* unbind_ptr(void* ptr)							// функция отвязки от корзины
{
	if(ptr)											// проверка существования указателя (указатель существует)
	{
		register usint i;							// счетчик

		for(i = 0; i < trash_p; ++i)				// цикл обхода существующих элементов корзины
		{
			if(ptr == trash[i])						// проверка текущего указателя (текущий указатель - искомый)
			{
				--trash_p;							// декремент значения указателя последнего элемента корзины

				trash[i]		= trash[trash_p];	// перезапись очищенной ячейки последней занятой ячейкой корзины
				trash[trash_p]	= NULL;				// обнуление последней занятой ячейки

				return ptr;							// возвращаем отвязанный указатель
			}
		}
	}

	return ptr;										// возвращаем отвязанный указатель
}
//===================================================================================================================================
void show_trash(string path)
{
	#ifdef SHOW_TRASH
	register usint i;

	printf("= TRASH (%s) =\n", path);

	for(i = 0; i < MAX_ALLOCATED_MEM; ++i)
	{
		if(trash[i])
			printf("%u:\t%p\n", i, trash[i]);
	}
	#endif
}
//===================================================================================================================================
void clear_trash(void)          	// функция очищения памяти
{
	register uint i;            	// счетчик

	for(i = 0; i < trash_p; ++i)	// обход корзины
	{
		free(trash[i]);       		// очищение памяти
		trash[i] = NULL;			// обнуление указателя
	}

	trash_p = 0;                	// сброс счетчика заполненности корзины
}
//===================================================================================================================================
void prints(string str)         // функция вывода строки
{
	register uint i;            // счетчик

	for(i = 0; str[i]!=EOS; ++i)// цикл обхода всех элементов строки
		putchar(str[i]);        // вывод символа
}
//===================================================================================================================================
uint get_hash(string str)				// функция получения хэша
{
	register uint	i;					// счетчик
	uint			hash	= 0;		// переменная для хранения хэша

	for(i = 0; str[i]!=EOS; ++i)		// цикл обхода строки
		hash += (int)str[i] * (i + 1);	// запись хэша

	return hash;						// возвращаем хэш
}
//===================================================================================================================================
uint str_len(string str)			// функция подсчета длины строки
{
	register uint i;				// счетчик

	for(i = 0; str[i] != EOS; ++i);	// цикл обхода всей строки и подсчет символов

	return i;						// возвращаем количество символов в строке
}
//===================================================================================================================================
string get_value(string* args, int argc, string flag)									// функция получения флага из строки
{
	register uint i;																	// счетчик

	for(i = 0; i < argc; ++i)															// обход всех аргументов
		if(args[i][0] == '-')															// проверка первого символа (первый символ -)
			if(get_hash(get_str(args[i], 1, str_len(args[i]) - 1)) == get_hash(flag))	//
				return args[i + 1];

	return NULL;
}
//===================================================================================================================================
pth_t get_path(pth_t path)
{
	usint	chars		= 0,
			lastslash	= 0;

	while(path[chars] != EOS)
	{
		++chars;

		if(path[chars] == '\\' or path[chars] == '/')
			lastslash = chars;
	}

	pth_t tmp = malloc((lastslash + 1) * sizeof(pth_t));

	register usint i;

	for(i = 0; i < lastslash; ++i)
        tmp[i] = path[i];

	tmp[lastslash] = EOS;

	return tmp;
}
//===================================================================================================================================
/*string cgets(int max_size)
{
	return NULL;
}*/
//===================================================================================================================================

#endif
